package com.powernode.config;

import com.powernode.filter.AppJwtCheckFilter;
import com.powernode.handler.AppAccessDeniedHandler;
import com.powernode.handler.AppAuthenticationFailureHandler;
import com.powernode.handler.AppAuthenticationSuccessHandler;
import com.powernode.handler.AppLogoutSuccessHandler;
import com.powernode.service.impl.AppUserServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
public class MySecurityConfiguration {
    @Resource
    private AppAuthenticationSuccessHandler appAuthenticationSuccessHandler;
    @Resource
    private AppAuthenticationFailureHandler appAuthenticationFailureHandler;
    @Resource
    private AppAccessDeniedHandler appAccessDeniedHandler;
    @Resource
    private AppLogoutSuccessHandler appLogoutSuccessHandler;

    @Resource
    private AppUserServiceImpl appUserService;

    @Resource
    private AppJwtCheckFilter appJwtCheckFilter;

    /**
     * 配置安全过滤器链
     * @param httpSecurity
     * @return
     * @throws Exception
     */
//    @Bean
//    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
//
//        //让验证码的过滤器在用户名和密码过滤器之前运行
//        httpSecurity.addFilterBefore(captchaCodeFilter, UsernamePasswordAuthenticationFilter.class);
//        // 配置用户认证服务
//        httpSecurity.userDetailsService(appUserService);
//        // 配置没有权限的handler
//        httpSecurity.exceptionHandling(handler->handler.accessDeniedHandler(appAccessDeniedHandler));
//        // 配置成功和失败的handler
//        httpSecurity.formLogin(handler->handler
//                .usernameParameter("uname") //默认用户名参数名是username
//                .passwordParameter("pwd") //默认密码参数名是password
//                .loginPage("/Login") //默认登录页面是/Login
//                .loginProcessingUrl("/login") //默认处理登录请求的url是/login
//                .successHandler(appAuthenticationSuccessHandler)
//                .failureHandler(appAuthenticationFailureHandler));
//
//        //放行登录等请求，不需要security检查token的地址
//        httpSecurity.authorizeHttpRequests(requests->requests
//                .requestMatchers("/Login","/login","/code/captcha")
//                .permitAll()
//                .anyRequest().authenticated());
//
//
//        //关闭csrf
//        httpSecurity.csrf(csrf ->csrf.disable());
//
//        //允许前端跨域访问
//        //httpSecurity.cors(cors->cors.disable());
//        //跨域配置
//        httpSecurity.cors(cors -> { //允许前端跨域访问
//            cors.configurationSource(configurationSource());
//        });
//
//
//
//        // 配置登出的handler
//        httpSecurity.logout(handler->handler.logoutSuccessHandler(appLogoutSuccessHandler));
//        return httpSecurity.build();
//    }
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {

        //设置jwt过滤器执行顺序在用户名和密码验证的过滤器之前

        httpSecurity.addFilterBefore(appJwtCheckFilter, UsernamePasswordAuthenticationFilter.class);

        //让验证码的过滤器在用户名和密码过滤器之前运行
        //httpSecurity.addFilterBefore(captchaCodeFilter, UsernamePasswordAuthenticationFilter.class);

        //-----------新增 配置我们自己的AppUserServiceImpl
        httpSecurity.userDetailsService(appUserService);


        //配置没有权限的handler
        httpSecurity.exceptionHandling(handler -> handler.accessDeniedHandler(appAccessDeniedHandler));

        //配置认证成功和失败的handler
        httpSecurity.formLogin(handler -> handler
                .usernameParameter("uname")//----新增 默认获取的是username
                .passwordParameter("pwd") //----新增 默认获取的是password
                .loginPage("/Login")  //----新增 跳转到登录页面的Controller地址
                .loginProcessingUrl("/login")//----新增 处理请求的地址
                .successHandler(appAuthenticationSuccessHandler)
                .failureHandler(appAuthenticationFailureHandler));

        //放行登录等请求  不需要security验证token的地址写到这里
        //除了/toLogin /login/doLogin 之外的其他请求，都需要security验证token
        httpSecurity.authorizeHttpRequests(request ->
                request.requestMatchers("/Login", "/login","/code/image")
                        .permitAll()
                        .anyRequest().authenticated());

        //关闭csrf
        httpSecurity.csrf(csrf -> csrf.disable());
        //允许前端跨域访问
        //httpSecurity.cors(cors -> cors.disable());


        //禁用session
        httpSecurity.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));


        //配置退出的handler
        httpSecurity.logout(handler -> handler.logoutSuccessHandler(appLogoutSuccessHandler));


        //跨域配置
        httpSecurity.cors(cors -> { //允许前端跨域访问
            cors.configurationSource(configurationSource());
        });

        return httpSecurity.build();
    }


    /**
     * 配置加密器
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }



    @Bean //配置跨域
    public CorsConfigurationSource configurationSource() {
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();

        //跨域配置
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOrigins(Arrays.asList("*")); //允许任何来源，http://localhost:10492/
        corsConfiguration.setAllowedMethods(Arrays.asList("*")); //允许任何请求方法，post、get、put、delete
        corsConfiguration.setAllowedHeaders(Arrays.asList("*")); //允许任何的请求头 (jwt)

        //注册跨域配置
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); //  /api/user,  /api/user/12082
        return urlBasedCorsConfigurationSource;
    }
}
